﻿using jvm.instructions.common;
using jvm.rtda;
using jvm.rtda.heap;
using jvm.rtda.heap.clazz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.instructions.references
{
    class ArrayType
    {
        public const byte AT_BOOLEAN = 4;
        public const byte AT_CHAR = 5;
        public const byte AT_FLOAT = 6;
        public const byte AT_DOUBLE = 7;
        public const byte AT_BYTE = 8;
        public const byte AT_SHORT = 9;
        public const byte AT_INT = 10;
        public const byte AT_LONG = 11;
    }

    class NEW_ARRAY : Instruction
    {
        public byte atype;

        public override void FetchOperands(ByteCodeReader reader)
        {
            atype = reader.ReadUint8();
        }

        public override void Execute(JFrame frame)
        {
            int count=frame.operandStack.PopInt();
            if (count < 0)
            {
                Console.WriteLine("java.lang.NegativeArraySizeException");
                Environment.Exit(0);
            }
            JClass jClass = GetPrimitiveClass(frame.method.jClass.loader, atype);
            JObject obj = jClass.NewArray((uint)count);
            frame.operandStack.PushRef(obj);
        }

        JClass GetPrimitiveClass(JClassLoader loader, byte atype)
        {
            switch (atype)
            {
                case ArrayType.AT_BOOLEAN:
                    return loader.LoadClass("[Z");
                case ArrayType.AT_BYTE:
                    return loader.LoadClass("[B");
                case ArrayType.AT_CHAR:
                    return loader.LoadClass("[C");
                case ArrayType.AT_SHORT:
                    return loader.LoadClass("[S");
                case ArrayType.AT_INT:
                    return loader.LoadClass("[I");
                case ArrayType.AT_LONG:
                    return loader.LoadClass("[L");
                case ArrayType.AT_FLOAT:
                    return loader.LoadClass("[F");
                case ArrayType.AT_DOUBLE:
                    return loader.LoadClass("[D");
                default:
                    Console.WriteLine("Invalid atype");
                    Environment.Exit(0);
                    return null;
            }
        }
    }
}
